import os

import pygame as pg

# 用户数据及日志存储路径
if os.name == 'nt':   # Windows系统存储路径
    USERDATA_PATH = os.path.expandvars(
        os.path.join('%APPDATA%', 'pypvz', 'userdata.json')
    )
    USERLOG_PATH = os.path.expandvars(
        os.path.join('%APPDATA%', 'pypvz', 'run.log')
    )
else:   # 非Windows系统存储路径
    USERDATA_PATH = os.path.expanduser(
        os.path.join('~', '.config', 'pypvz', 'userdata.json')
    )
    USERLOG_PATH = os.path.expanduser(
        os.path.join('~', '.config', 'pypvz', 'run.log')
    )

# 游戏图片资源路径
PATH_IMG_DIR = os.path.join(
    os.path.dirname(os.path.dirname(__file__)), 'resources', 'graphics'
)
# 游戏音乐文件夹路径
PATH_MUSIC_DIR = os.path.join(
    os.path.dirname(os.path.dirname(__file__)), 'resources', 'music'
)
# 窗口图标
ORIGINAL_LOGO = os.path.join(
    os.path.dirname(os.path.dirname(__file__)), 'pypvz-exec-logo.png'
)
# 字体路径
FONT_PATH = os.path.join(
    os.path.dirname(os.path.dirname(__file__)),
    'resources',
    'DroidSansFallback.ttf',
)

# 窗口标题
ORIGINAL_CAPTION = 'pypvz'

# 游戏模式
GAME_MODE = 'mode'
MODE_ADVENTURE = 'adventure'
MODE_LITTLEGAME = 'littleGame'

# 窗口大小
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
SCREEN_SIZE = (SCREEN_WIDTH, SCREEN_HEIGHT)


# 选卡数量
# 最大数量
CARD_MAX_NUM = 10   # 这里以后可以增加解锁功能，从最初的6格逐渐解锁到10格
# 最小数量
CARD_LIST_NUM = CARD_MAX_NUM

# 方格数据
# 一般
GRID_X_LEN = 9
GRID_Y_LEN = 5
GRID_X_SIZE = 80
GRID_Y_SIZE = 100
# 带有泳池
GRID_POOL_X_LEN = GRID_X_LEN
GRID_POOL_Y_LEN = 6
GRID_POOL_X_SIZE = GRID_X_SIZE
GRID_POOL_Y_SIZE = 85
# 屋顶
GRID_ROOF_X_LEN = GRID_X_LEN
GRID_ROOF_Y_LEN = GRID_Y_LEN
GRID_ROOF_X_SIZE = GRID_X_SIZE
GRID_ROOF_Y_SIZE = 85

# 颜色
WHITE = (255, 255, 255)
NAVYBLUE = (60, 60, 100)
SKY_BLUE = (39, 145, 251)
BLACK = (0, 0, 0)
LIGHTYELLOW = (234, 233, 171)
RED = (255, 0, 0)
PURPLE = (255, 0, 255)
GOLD = (255, 215, 0)
GREEN = (0, 255, 0)
YELLOWGREEN = (55, 200, 0)
LIGHTGRAY = (107, 108, 145)
PARCHMENT_YELLOW = (207, 146, 83)

# 退出游戏按钮
EXIT = 'exit'
HELP = 'help'
# 游戏界面可选的菜单
LITTLE_MENU = 'littleMenu'
BIG_MENU = 'bigMenu'
RESTART_BUTTON = 'restartButton'
MAINMENU_BUTTON = 'mainMenuButton'
LITTLEGAME_BUTTON = 'littleGameButton'
OPTION_BUTTON = 'optionButton'
SOUND_VOLUME_BUTTON = 'volumeButton'
UNIVERSAL_BUTTON = 'universalButton'
# 金银向日葵奖杯
TROPHY_SUNFLOWER = 'sunflowerTrophy'
# 小铲子
SHOVEL = 'shovel'
SHOVEL_BOX = 'shovelBox'
# 一大波僵尸来袭图片
HUGE_WAVE_APPROCHING = 'Approching'
# 关卡进程图片
LEVEL_PROGRESS_BAR = 'LevelProgressBar'
LEVEL_PROGRESS_ZOMBIE_HEAD = 'LevelProgressZombieHead'
LEVEL_PROGRESS_FLAG = 'LevelProgressFlag'


# GAME INFO字典键值
CURRENT_TIME = 'current time'
PASSED_ALL = 'passed all'   # 已完成该模式下的所有游戏，应当显示向日葵奖杯获得界面
LEVEL_NUM = 'level num'
LITTLEGAME_NUM = 'littleGame num'
LEVEL_COMPLETIONS = 'level completions'
LITTLEGAME_COMPLETIONS = 'littleGame completions'
GAME_RATE = 'game rate'
SOUND_VOLUME = 'volume'

# 整个游戏的状态
MAIN_MENU = 'main menu'
LOAD_SCREEN = 'load screen'
GAME_LOSE = 'game lose'
GAME_VICTORY = 'game victory'
LEVEL = 'level'
AWARD_SCREEN = 'award screen'
HELP_SCREEN = 'help screen'

# 界面图片文件名
MAIN_MENU_IMAGE = 'MainMenu'
OPTION_ADVENTURE = 'Adventure'
GAME_LOSE_IMAGE = 'GameLose'
GAME_VICTORY_IMAGE = 'GameVictory'
AWARD_SCREEN_IMAGE = 'AwardScreen'
HELP_SCREEN_IMAGE = 'HelpScreen'

# 地图相关内容
BACKGROUND_NAME = 'Background'
BACKGROUND_TYPE = 'background_type'
INIT_SUN_NAME = 'init_sun_value'
ZOMBIE_LIST = 'zombie_list'
GAME_TITLE = 'title'

# 地图类型
BACKGROUND_DAY = 0
BACKGROUND_NIGHT = 1
BACKGROUND_POOL = 2
BACKGROUND_FOG = 3
BACKGROUND_ROOF = 4
BACKGROUND_ROOFNIGHT = 5
BACKGROUND_WALLNUTBOWLING = 6
BACKGROUND_SINGLE = 7
BACKGROUND_TRIPLE = 8

# 地图类型集合
# 白天场地（泛指蘑菇睡觉的场地）
DAYTIME_BACKGROUNDS = {
    BACKGROUND_DAY,
    BACKGROUND_POOL,
    BACKGROUND_ROOF,
    BACKGROUND_WALLNUTBOWLING,
    BACKGROUND_SINGLE,
    BACKGROUND_TRIPLE,
}

# 带有泳池的场地
POOL_EQUIPPED_BACKGROUNDS = {
    BACKGROUND_POOL,
    BACKGROUND_FOG,
}

# 屋顶上的场地
ON_ROOF_BACKGROUNDS = {
    BACKGROUND_ROOF,
    BACKGROUND_ROOFNIGHT,
}

# BACKGROUND_DAY场地的变体
BACKGROUND_DAY_LIKE_BACKGROUNDS = {
    BACKGROUND_DAY,
    BACKGROUND_SINGLE,
    BACKGROUND_TRIPLE,
}

# 夜晚地图的墓碑数量等级
GRADE_GRAVES = 'grade_graves'
# 不同墓碑等级对应的信息，列表位置对应的是墓碑等级
GRAVES_GRADE_INFO = (0, 4, 7, 11)

# 僵尸生成方式
SPAWN_ZOMBIES = 'spawn_zombies'
SPAWN_ZOMBIES_AUTO = 1
SPAWN_ZOMBIES_LIST = 0
INCLUDED_ZOMBIES = 'included_zombies'
NUM_FLAGS = 'num_flags'
INEVITABLE_ZOMBIE_DICT = 'inevitable_zombie_list'
SURVIVAL_ROUNDS = 'survival_rounds'

# 地图单元格属性
MAP_PLANT = 'plantnames'
MAP_SLEEP = 'sleep'   # 有没有休眠的蘑菇，作是否能种植咖啡豆的判断
MAP_PLOT_TYPE = 'plot_type'
# 地图单元格区域类型
MAP_GRASS = 'grass'
MAP_WATER = 'water'
MAP_TILE = 'tile'  # 指屋顶上的瓦片
MAP_UNAVAILABLE = 'unavailable'   # 指完全不能种植物的地方，包括无草皮的荒地和坚果保龄球等红线右侧

# 地图相关像素数据
BACKGROUND_OFFSET_X = 220
MAP_OFFSET_X = 35
MAP_OFFSET_Y = 100
MAP_POOL_OFFSET_X = 42
MAP_POOL_OFFSET_Y = 115
MAP_ROOF_OFFSET_X = 35  # 暂时还不清楚数据
MAP_ROOF_OFFSET_Y = 105   # 暂时还不清楚数据

# 泳池前端陆地部分
MAP_POOL_FRONT_X = SCREEN_WIDTH - 15

# 植物选择菜单栏、传送带菜单栏等类型设定
CHOOSEBAR_TYPE = 'choosebar_type'
CHOOSEBAR_STATIC = 0
CHOOSEBAR_MOVE = 1
CHOOSEBAR_BOWLING = 2
MENUBAR_BACKGROUND = 'ChooserBackground'
MOVEBAR_BACKGROUND = 'MoveBackground'
PANEL_BACKGROUND = 'PanelBackground'
START_BUTTON = 'StartButton'
CARD_POOL = 'card_pool'

# 关于植物栏的像素设置
PANEL_Y_START = 87
PANEL_X_START = 22
PANEL_Y_INTERNAL = 69
PANEL_X_INTERNAL = 53
BAR_CARD_X_INTERNAL = 51

# 植物卡片信息索引
PLANT_NAME_INDEX = 0
CARD_INDEX = 1
SUN_INDEX = 2
FROZEN_TIME_INDEX = 3

# 传送带模式中的刷新间隔和移动速率
MOVEBAR_CARD_FRESH_TIME = 6000
CARD_MOVE_TIME = 60

# 其他显示物
CAR = 'car'
SUN = 'Sun'

# plant子类非植物对象（这里的是不包括阳光、子弹的拟植物对象）
NON_PLANT_OBJECTS = {
    HOLE := 'Hole',
    ICEFROZENPLOT := 'IceFrozenPlot',
    GRAVE := 'Grave',
}

# 植物相关信息
PLANT_IMAGE_RECT = 'plant_image_rect'
BOOM_IMAGE = 'Boom'

# 植物卡片信息汇总（包括植物名称, 卡片名称, 阳光, 冷却时间）
PLANT_CARD_INFO = (  # 元组 (植物名称, 卡片名称, 阳光, 冷却时间)
    (
        PEASHOOTER := 'Peashooter',
        CARD_PEASHOOTER := 'card_peashooter',
        100,
        7500,
    ),
    (SUNFLOWER := 'SunFlower', CARD_SUNFLOWER := 'card_sunflower', 50, 7500),
    (
        CHERRYBOMB := 'CherryBomb',
        CARD_CHERRYBOMB := 'card_cherrybomb',
        150,
        50000,
    ),
    (WALLNUT := 'WallNut', CARD_WALLNUT := 'card_wallnut', 50, 30000),
    (
        POTATOMINE := 'PotatoMine',
        CARD_POTATOMINE := 'card_potatomine',
        25,
        30000,
    ),
    (
        SNOWPEASHOOTER := 'SnowPea',
        CARD_SNOWPEASHOOTER := 'card_snowpea',
        175,
        7500,
    ),
    (CHOMPER := 'Chomper', CARD_CHOMPER := 'card_chomper', 150, 7500),
    (
        REPEATERPEA := 'RepeaterPea',
        CARD_REPEATERPEA := 'card_repeaterpea',
        200,
        7500,
    ),
    (
        PUFFSHROOM := 'PuffShroom',
        CARD_PUFFSHROOM := 'card_puffshroom',
        0,
        7500,
    ),
    (SUNSHROOM := 'SunShroom', CARD_SUNSHROOM := 'card_sunshroom', 25, 7500),
    (
        FUMESHROOM := 'FumeShroom',
        CARD_FUMESHROOM := 'card_fumeshroom',
        75,
        7500,
    ),
    (
        GRAVEBUSTER := 'GraveBuster',
        CARD_GRAVEBUSTER := 'card_gravebuster',
        75,
        7500,
    ),
    (
        HYPNOSHROOM := 'HypnoShroom',
        CARD_HYPNOSHROOM := 'card_hypnoshroom',
        75,
        30000,
    ),
    (
        SCAREDYSHROOM := 'ScaredyShroom',
        CARD_SCAREDYSHROOM := 'card_scaredyshroom',
        25,
        7500,
    ),
    (ICESHROOM := 'IceShroom', CARD_ICESHROOM := 'card_iceshroom', 75, 50000),
    (
        DOOMSHROOM := 'DoomShroom',
        CARD_DOOMSHROOM := 'card_doomshroom',
        125,
        50000,
    ),
    (LILYPAD := 'LilyPad', CARD_LILYPAD := 'card_lilypad', 25, 7500),
    (SQUASH := 'Squash', CARD_SQUASH := 'card_squash', 50, 30000),
    (
        TANGLEKLEP := 'TangleKlep',
        CARD_TANGLEKLEP := 'card_tangleklep',
        25,
        30000,
    ),
    (
        THREEPEASHOOTER := 'Threepeater',
        CARD_THREEPEASHOOTER := 'card_threepeashooter',
        325,
        7500,
    ),
    (JALAPENO := 'Jalapeno', CARD_JALAPENO := 'card_jalapeno', 125, 50000),
    (SPIKEWEED := 'Spikeweed', CARD_SPIKEWEED := 'card_spikeweed', 100, 7500),
    (TORCHWOOD := 'TorchWood', CARD_TORCHWOOD := 'card_torchwood', 175, 7500),
    (TALLNUT := 'TallNut', CARD_TALLNUT := 'card_tallnut', 125, 30000),
    (SEASHROOM := 'SeaShroom', CARD_SEASHROOM := 'card_seashroom', 0, 30000),
    (STARFRUIT := 'StarFruit', CARD_STARFRUIT := 'card_starfruit', 125, 7500),
    (
        PUMPKINHEAD := 'PumpkinHead',
        CARD_PUMPKINHEAD := 'card_pumpkinhead',
        125,
        30000,
    ),
    (
        COFFEEBEAN := 'CoffeeBean',
        CARD_COFFEEBEAN := 'card_coffeebean',
        75,
        7500,
    ),
    (GARLIC := 'Garlic', CARD_GARLIC := 'card_garlic', 50, 7500),
    # 应当保证这3个在一般模式下不可选的特殊植物恒在最后
    (WALLNUTBOWLING := 'WallNutBowling', CARD_WALLNUT := 'card_wallnut', 0, 0),
    (
        REDWALLNUTBOWLING := 'RedWallNutBowling',
        CARD_REDWALLNUT := 'card_redwallnut',
        0,
        0,
    ),
    (
        GIANTWALLNUT := 'GiantWallNut',
        CARD_GIANTWALLNUT := 'card_giantwallnut',
        0,
        0,
    ),
)

# 卡片中的植物名称与索引序号的对应关系，指定名称以得到索引值
PLANT_CARD_INDEX = {
    item[PLANT_NAME_INDEX]: index
    for (index, item) in enumerate(PLANT_CARD_INFO)
}

# 指定了哪些卡可选（排除坚果保龄球特殊植物）
CARDS_TO_CHOOSE = range(len(PLANT_CARD_INFO) - 3)


# 植物集体属性集合
# 也许以后有必要的可以重新加入到对象的属性中
# 在生效时不用与僵尸进行碰撞检测的对象（即生效时不可发生被僵尸啃食的事件）
SKIP_ZOMBIE_COLLISION_CHECK_WHEN_WORKING = {
    # 注意爆炸坚果的触发也是啃食类碰撞，因此只能算作爆炸后不检测
    SQUASH,
    ICESHROOM,
    REDWALLNUTBOWLING,
    CHERRYBOMB,
    JALAPENO,
    DOOMSHROOM,
    POTATOMINE,
}

# 所有可能不用与僵尸进行碰撞检测的对象
CAN_SKIP_ZOMBIE_COLLISION_CHECK = (  # 这里运用了集合运算
    # 注意这个外围的小括号是用来换行的
    # 各个部分末！尾！千！万！不！能！加！逗！号！！！
    # 生效时不检测的植物
    SKIP_ZOMBIE_COLLISION_CHECK_WHEN_WORKING
    |
    # 非植物对象
    NON_PLANT_OBJECTS
    |
    # 地刺类
    {
        SPIKEWEED,
    }
)

# 死亡时不触发音效的对象
PLANT_DIE_SOUND_EXCEPTIONS = {
    WALLNUTBOWLING,
    TANGLEKLEP,
    ICEFROZENPLOT,
    HOLE,
    GRAVE,
    JALAPENO,
    REDWALLNUTBOWLING,
    CHERRYBOMB,
    GIANTWALLNUT,
}

# 直接水生植物
WATER_PLANTS = {
    LILYPAD,
    SEASHROOM,
    TANGLEKLEP,
}

# 攻击状态检查类型
CHECK_ATTACK_NEVER = 0
CHECK_ATTACK_ALWAYS = 1

# 范围爆炸植物，即灰烬植物与寒冰菇
ASH_PLANTS_AND_ICESHROOM = {
    REDWALLNUTBOWLING,
    CHERRYBOMB,
    JALAPENO,
    DOOMSHROOM,
    ICESHROOM,
}

# 白天要睡觉的植物
CAN_SLEEP_PLANTS = {
    PUFFSHROOM,
    SUNSHROOM,
    FUMESHROOM,
    HYPNOSHROOM,
    SCAREDYSHROOM,
    ICESHROOM,
    DOOMSHROOM,
    SEASHROOM,
}

# 选卡不推荐选择理由
REASON_WILL_SLEEP = 1
REASON_SLEEP_BUT_COFFEE_BEAN = 2
REASON_OTHER = 3

# 植物生命值
PLANT_HEALTH = 300
WALLNUT_HEALTH = 4000
WALLNUT_CRACKED1_HEALTH = WALLNUT_HEALTH // 3 * 2
WALLNUT_CRACKED2_HEALTH = WALLNUT_HEALTH // 3
TALLNUT_HEALTH = 8000
TALLNUT_CRACKED1_HEALTH = TALLNUT_HEALTH // 3 * 2
TALLNUT_CRACKED2_HEALTH = TALLNUT_HEALTH // 3
GARLIC_HEALTH = 450
GARLIC_CRACKED1_HEALTH = GARLIC_HEALTH // 3 * 2
GARLIC_CRACKED2_HEALTH = GARLIC_HEALTH // 3
# 坚果保龄球攻击伤害
WALLNUT_BOWLING_DAMAGE = 550

# 阳光生成属性
PRODUCE_SUN_INTERVAL = 4250   # 基准
FLOWER_SUN_INTERVAL = 24000
SUN_LIVE_TIME = 10000
SUN_VALUE = 25

# 僵尸冷冻
ICE_SLOW_TIME = 10000
MIN_FREEZE_TIME = 4000
ICETRAP = 'IceTrap'

# 子弹信息
# 子弹类型
BULLET_PEA = 'PeaNormal'
BULLET_PEA_ICE = 'PeaIce'
BULLET_FIREBALL = 'Fireball'
BULLET_MUSHROOM = 'BulletMushRoom'
BULLET_SEASHROOM = 'BulletSeaShroom'
FUME = 'Fume'
# 子弹伤害
BULLET_DAMAGE_NORMAL = 20
BULLET_DAMAGE_FIREBALL_BODY = 27   # 这是火球本体的伤害，注意不是40，本体(27) + 溅射(13)才是40
BULLET_DAMAGE_FIREBALL_RANGE = 13   # 原版溅射伤害会随着僵尸数量增多而减少，这里相当于做了一个增强
# 子弹效果
BULLET_EFFECT_ICE = 'ice'
BULLET_EFFECT_UNICE = 'unice'

# 特殊子弹
# 杨桃子弹
# 子弹名称
BULLET_STAR = 'StarBullet'
# 子弹方向
STAR_FORWARD_UP = 'forwardUp'   # 向前上方
STAR_FORWARD_DOWN = 'forwardDown'   # 向前下方
STAR_BACKWARD = 'backward'  # 向后
STAR_UPWARD = 'upward'  # 向上
STAR_DOWNWARD = 'downward'  # 向下

# 有爆炸图片的子弹
BULLET_INDEPENDENT_BOOM_IMG = {
    BULLET_PEA,
    BULLET_PEA_ICE,
    BULLET_MUSHROOM,
    BULLET_SEASHROOM,
    BULLET_STAR,
}

# 僵尸信息
ZOMBIE_IMAGE_RECT = 'zombie_image_rect'
ZOMBIE_HEAD = 'ZombieHead'
NORMAL_ZOMBIE = 'Zombie'
CONEHEAD_ZOMBIE = 'ConeheadZombie'
BUCKETHEAD_ZOMBIE = 'BucketheadZombie'
FLAG_ZOMBIE = 'FlagZombie'
NEWSPAPER_ZOMBIE = 'NewspaperZombie'
FOOTBALL_ZOMBIE = 'FootballZombie'
DUCKY_TUBE_ZOMBIE = 'DuckyTubeZombie'
CONEHEAD_DUCKY_TUBE_ZOMBIE = 'ConeheadDuckyTubeZombie'
BUCKETHEAD_DUCKY_TUBE_ZOMBIE = 'BucketheadDuckyTubeZombie'
SCREEN_DOOR_ZOMBIE = 'ScreenDoorZombie'
POLE_VAULTING_ZOMBIE = 'PoleVaultingZombie'
ZOMBONI = 'Zomboni'
SNORKELZOMBIE = 'SnorkelZombie'

BOOMDIE = 'BoomDie'

# 对僵尸的攻击类型设置
ZOMBIE_DEAFULT_DAMAGE = ZOMBIE_HELMET_2_FIRST = 'helmet2First'  # 优先攻击二类防具
ZOMBIE_COMMON_DAMAGE = 'commonDamage'   # 优先攻击僵尸与一类防具的整体
ZOMBIE_RANGE_DAMAGE = 'rangeDamage'   # 范围攻击，同时伤害二类防具与(僵尸与一类防具的整体)
ZOMBIE_ASH_DAMAGE = 'ashDamage'   # 灰烬植物攻击，直接伤害本体
ZOMBIE_WALLNUT_BOWLING_DANMAGE = 'wallnutBowlingDamage'   # 坚果保龄球冲撞伤害

# 僵尸生命值设置
# 有关本体
NORMAL_HEALTH = 200   # 普通僵尸生命值
POLE_VAULTING_HEALTH = 333
ZOMBONI_HEALTH = 1280
# 冰车损坏点
ZOMBONI_DAMAGED1_HEALTH = 2 * ZOMBONI_HEALTH // 3 + 70
ZOMBONI_DAMAGED2_HEALTH = ZOMBONI_HEALTH // 3 + 70
# 掉头后僵尸的生命值
LOSTHEAD_HEALTH = 70
POLE_VAULTING_LOSTHEAD_HEALTH = 167
# 有关一类防具
CONEHEAD_HEALTH = 370
BUCKETHEAD_HEALTH = 1100
FOOTBALL_HELMET_HEALTH = 1400
# 有关二类防具
NEWSPAPER_HEALTH = 150
SCREEN_DOOR_HEALTH = 1100

# 僵尸行动信息
ATTACK_INTERVAL = 500
ZOMBIE_ATTACK_DAMAGE = 50
ZOMBIE_WALK_INTERVAL = 60  # 僵尸步行间隔

# 僵尸生成位置
ZOMBIE_START_X = SCREEN_WIDTH + 30  # 场宽度不一样，用于拟合


# 僵尸集体属性集合
# 僵尸生成信息字典：包含生成僵尸名称、僵尸级别、生成权重
CREATE_ZOMBIE_DICT = {  # 生成僵尸:(级别, 权重)
    NORMAL_ZOMBIE: (1, 4000),
    FLAG_ZOMBIE: (1, 0),
    CONEHEAD_ZOMBIE: (2, 4000),
    BUCKETHEAD_ZOMBIE: (4, 3000),
    NEWSPAPER_ZOMBIE: (2, 1000),
    FOOTBALL_ZOMBIE: (7, 2000),
    DUCKY_TUBE_ZOMBIE: (1, 0),  # 作为变种，不主动生成
    CONEHEAD_DUCKY_TUBE_ZOMBIE: (2, 0),  # 作为变种，不主动生成
    BUCKETHEAD_DUCKY_TUBE_ZOMBIE: (4, 0),  # 作为变种，不主动生成
    SCREEN_DOOR_ZOMBIE: (4, 3500),
    POLE_VAULTING_ZOMBIE: (2, 2000),
    ZOMBONI: (7, 2000),
    SNORKELZOMBIE: (3, 2000),
}

# 记录陆生僵尸的水生变种
CONVERT_ZOMBIE_IN_POOL = {
    NORMAL_ZOMBIE: DUCKY_TUBE_ZOMBIE,
    CONEHEAD_ZOMBIE: CONEHEAD_DUCKY_TUBE_ZOMBIE,
    BUCKETHEAD_ZOMBIE: BUCKETHEAD_DUCKY_TUBE_ZOMBIE,
}

# 水上僵尸集合
WATER_ZOMBIE = {
    DUCKY_TUBE_ZOMBIE,
    CONEHEAD_DUCKY_TUBE_ZOMBIE,
    BUCKETHEAD_DUCKY_TUBE_ZOMBIE,
    SNORKELZOMBIE,
}


# 状态类型
IDLE = 'idle'
FLY = 'fly'
EXPLODE = 'explode'
ATTACK = 'attack'
ATTACKED = 'attacked'
DIGEST = 'digest'
WALK = 'walk'
DIE = 'die'
CRY = 'cry'
FREEZE = 'freeze'
SLEEP = 'sleep'

# 关卡状态
CHOOSE = 'choose'
PLAY = 'play'

# 加载矩形碰撞范围 用于消除文件边框影响
# 植物
PLANT_RECT = {
    BULLET_PEA: {'x': 28, 'y': 0, 'width': 28, 'height': 34},
    BULLET_PEA_ICE: {'x': 26, 'y': 0, 'width': 30, 'height': 34},
    CHOMPER: {'x': 0, 'y': 0, 'width': 100, 'height': 114},
    PUFFSHROOM: {'x': 0, 'y': 28, 'width': 35, 'height': 38},
    f'{PUFFSHROOM}Sleep': {'x': 1, 'y': 0, 'width': 39, 'height': 65},
    BULLET_MUSHROOM: {'x': 0, 'y': 1, 'width': 55, 'height': 21},
    BULLET_SEASHROOM: {'x': 0, 'y': 1, 'width': 55, 'height': 21},
    POTATOMINE: {'x': 0, 'y': 0, 'width': 75, 'height': 55},
    SQUASH: {'x': 10, 'y': 140, 'width': 80, 'height': 86},
    f'{SQUASH}Aim': {'x': 10, 'y': 140, 'width': 80, 'height': 86},
    SPIKEWEED: {'x': 3, 'y': 0, 'width': 80, 'height': 35},
}
# 僵尸
ZOMBIE_RECT = {
    NORMAL_ZOMBIE: {'x': 62, 'width': 90},
    f'{NORMAL_ZOMBIE}Attack': {'x': 62, 'width': 90},
    f'{NORMAL_ZOMBIE}LostHead': {'x': 62, 'width': 90},
    f'{NORMAL_ZOMBIE}LostHeadAttack': {'x': 62, 'width': 90},
    f'{NORMAL_ZOMBIE}Die': {'x': 0, 'width': 164},
    BOOMDIE: {'x': 68, 'width': 80},
    CONEHEAD_ZOMBIE: {'x': 80, 'width': 80},
    f'{CONEHEAD_ZOMBIE}Attack': {'x': 79, 'width': 87},
    BUCKETHEAD_ZOMBIE: {'x': 54, 'width': 90},
    f'{BUCKETHEAD_ZOMBIE}Attack': {'x': 46, 'width': 90},
    FLAG_ZOMBIE: {'x': 56, 'width': 110},
    f'{FLAG_ZOMBIE}Attack': {'x': 60, 'width': 100},
    f'{FLAG_ZOMBIE}LostHead': {'x': 55, 'width': 110},
    f'{FLAG_ZOMBIE}LostHeadAttack': {'x': 55, 'width': 110},
    NEWSPAPER_ZOMBIE: {'x': 48, 'width': 92},
    f'{NEWSPAPER_ZOMBIE}Attack': {'x': 48, 'width': 92},
    f'{NEWSPAPER_ZOMBIE}NoPaper': {'x': 40, 'width': 98},
    f'{NEWSPAPER_ZOMBIE}NoPaperAttack': {'x': 48, 'width': 92},
    f'{NEWSPAPER_ZOMBIE}LostHead': {'x': 44, 'width': 96},
    f'{NEWSPAPER_ZOMBIE}LostHeadAttack': {'x': 48, 'width': 92},
    f'{NEWSPAPER_ZOMBIE}Die': {'x': 0, 'width': 100},
    f'{DUCKY_TUBE_ZOMBIE}Die': {'x': 55, 'width': 105},
    f'{DUCKY_TUBE_ZOMBIE}LostHead': {'x': 55, 'width': 105},
    SCREEN_DOOR_ZOMBIE: {'x': 41, 'width': 100},
    f'{SCREEN_DOOR_ZOMBIE}Attack': {'x': 41, 'width': 100},
}   # 这里还有懒得写代码的补加，用循环实现
for _part1 in (
    DUCKY_TUBE_ZOMBIE,
    CONEHEAD_DUCKY_TUBE_ZOMBIE,
    BUCKETHEAD_DUCKY_TUBE_ZOMBIE,
):
    for _part2 in ('', 'Attack', 'Swim'):
        ZOMBIE_RECT[f'{_part1}{_part2}'] = {'x': 55, 'width': 105}


# 音效
def _getSound(filename):
    return pg.mixer.Sound(
        os.path.join(
            os.path.dirname(os.path.dirname(__file__)),
            'resources',
            'sound',
            filename,
        )
    )


# 所有音效的元组，用一波海象算子表达，免得要维护两个
SOUNDS = (  # 程序交互等
    SOUND_TAPPING_CARD := _getSound('tap.ogg'),
    SOUND_HELP_SCREEN := _getSound('helpScreen.ogg'),
    # 植物
    SOUND_FIREPEA_EXPLODE := _getSound('firepea.ogg'),
    SOUND_BULLET_EXPLODE := _getSound('bulletExplode.ogg'),
    SOUND_SHOOT := _getSound('shoot.ogg'),
    SOUND_SNOWPEA_SPARKLES := _getSound('snowPeaSparkles.ogg'),
    SOUND_BOMB := _getSound('bomb.ogg'),
    SOUND_BIGCHOMP := _getSound('bigchomp.ogg'),
    SOUND_PUFF := _getSound('puff.ogg'),
    SOUND_POTATOMINE := _getSound('potatomine.ogg'),
    SOUND_SQUASHING := _getSound('squashing.ogg'),
    SOUND_SQUASH_HMM := _getSound('squashHmm.ogg'),
    SOUND_PLANT_GROW := _getSound('plantGrow.ogg'),
    SOUND_MUSHROOM_WAKEUP := _getSound('mushroomWakeup.ogg'),
    SOUND_TANGLE_KELP_DRAG := _getSound('tangleKelpDrag.ogg'),
    SOUND_DOOMSHROOM := _getSound('doomshroom.ogg'),
    SOUND_GRAVEBUSTER_CHOMP := _getSound('gravebusterchomp.ogg'),
    SOUND_FUME := _getSound('fume.ogg'),
    # 僵尸
    SOUND_ZOMBIE_ENTERING_WATER := _getSound('zombieEnteringWater.ogg'),
    SOUND_ZOMBIE_ATTACKING := _getSound('zombieAttack.ogg'),
    SOUND_FREEZE := _getSound('freeze.ogg'),
    SOUND_HYPNOED := _getSound('hypnoed.ogg'),
    SOUND_NEWSPAPER_RIP := _getSound('newspaperRip.ogg'),
    SOUND_NEWSPAPER_ZOMBIE_ANGRY := _getSound('newspaperZombieAngry.ogg'),
    SOUND_POLEVAULT_JUMP := _getSound('polevaultjump.ogg'),
    SOUND_ZOMBONI := _getSound('zomboni.ogg'),
    SOUND_ZOMBONI_EXPLOSION := _getSound('zomboniExplosion.ogg'),
    # 关卡中
    SOUND_CAR_WALKING := _getSound('carWalking.ogg'),
    SOUND_ZOMBIE_COMING := _getSound('zombieComing.ogg'),
    SOUND_ZOMBIE_VOICE := _getSound('zombieVoice.ogg'),
    SOUND_HUGE_WAVE_APPROCHING := _getSound('hugeWaveApproching.ogg'),
    SOUND_BUTTON_CLICK := _getSound('buttonclick.ogg'),
    SOUND_COLLECT_SUN := _getSound('collectSun.ogg'),
    SOUND_CLICK_CARD := _getSound('clickCard.ogg'),
    SOUND_SHOVEL := _getSound('shovel.ogg'),
    SOUND_PLANT := _getSound('plant.ogg'),
    SOUND_BOWLING_IMPACT := _getSound('bowlingimpact.ogg'),
    SOUND_PLANT_DIE := _getSound('plantDie.ogg'),
    SOUND_EVILLAUGH := _getSound('evillaugh.ogg'),
    SOUND_LOSE := _getSound('lose.ogg'),
    SOUND_WIN := _getSound('win.ogg'),
    SOUND_SCREAM := _getSound('scream.ogg'),
    SOUND_CANNOT_CHOOSE_WARNING := _getSound('cannotChooseWarning.ogg'),
    SOUND_FINAL_FANFARE := _getSound('finalfanfare.ogg'),
)

# 记录本地存储文件初始值
INIT_USERDATA = {
    LEVEL_NUM: 1,
    LITTLEGAME_NUM: 1,
    LEVEL_COMPLETIONS: 0,
    LITTLEGAME_COMPLETIONS: 0,
    GAME_RATE: 1,
    SOUND_VOLUME: 1,
}

# 无穷大常量
INF = float('inf')  # python传递字符串性能较低，故在这里对inf声明一次，以后仅需调用即可，虽然真正的用处是可以自动补全（
